home *** CD-ROM | disk | FTP | other *** search
/ Reverse Code Engineering RCE CD +sandman 2000 / ReverseCodeEngineeringRceCdsandman2000.iso / RCE / Library / Manuels & Misc / Assembly / AOA.ZIP / CH16 / MADVENT.ASM < prev    next >
Encoding:
Assembly Source File  |  1994-07-11  |  23.0 KB  |  885 lines

  1. ; MADVENT.ASM
  2. ;
  3. ; This is a "shell" of an adventure game that you can use to create
  4. ; your own adventure style games.
  5.  
  6.         .xlist
  7.         .286
  8.         include     stdlib.a
  9.         includelib    stdlib.lib
  10.         matchfuncs
  11.         .list
  12.  
  13.  
  14.  
  15. dseg        segment        para public 'data'
  16.  
  17. ; Equates:
  18.  
  19. NULL        equ    0
  20. MaxWeight    equ    4    ;Max weight user can carry at one time.
  21.  
  22.  
  23. ; The "ROOM" data structure defines a room, or area, where a player can
  24. ; go.  The NORTH, SOUTH, EAST, and WEST fields contain the address of
  25. ; the rooms to the north, south, east, and west of the room.  The game
  26. ; transfers control to the room whose address appears in these fields
  27. ; when the player supplies a GO NORTH, GO SOUTH, etc., command.
  28. ;
  29. ; The ITEMLIST field contains a list of pointers to objects appearing
  30. ; in this room.  In this game, the user can pick up and drop these
  31. ; objects (if there are any present).
  32. ;
  33. ; The DESCRIPTION field contains a (near) address of a short description
  34. ; of the current room/area.
  35.  
  36. Room        struct
  37. north        word    ?    ;Near pointers to other structures where
  38. south        word    ?    ; we will wind up on the GO NORTH, GO SOUTH,
  39. west        word    ?    ; etc., commands.
  40. east        word    ?
  41.  
  42. ItemList    word    MaxWeight dup (?)
  43.  
  44. Description    word    ?    ;Description of room.
  45. Room        ends
  46.  
  47.  
  48. ; The ITEM data structure describes the objects that may appear
  49. ; within a room (in the ITEMLIST above).  The VALUE field contains
  50. ; the number of points this object is worth if the user drops it
  51. ; off in the proper room (i.e, solves the puzzle).  The WEIGHT
  52. ; field provides the weight of this object.  The user can only
  53. ; carry four units of weight at a time.  This field is usually
  54. ; one, but may be more for larger objects.  The KEY field is the
  55. ; address of the room where this object must be dropped to solve
  56. ; the problem.  The SHORTDESC field is a pointer to a string that
  57. ; the program prints when the user executes an INVENTORY command.
  58. ; LONGDESC is a pointer to a string the program prints when des-
  59. ; cribing the contents of a room.  The WINDESC field is a pointer
  60. ; to a string that the program prints when the user solves the
  61. ; appropriate puzzle.
  62.  
  63. Item        struct
  64. Value        word    ?
  65. Weight        word    ?
  66. Key        word    ?
  67. ShortDesc    word    ?
  68. LongDesc    word    ?
  69. WinDesc        word    ?
  70. Item        ends
  71.  
  72.  
  73.  
  74.  
  75.  
  76. ; State variables for the player:
  77.  
  78. CurRoom        word        Room1          ;Room the player is in.
  79. ItemsOnHand    word        MaxWeight dup (?) ;Items the player carries.
  80. CurWeight    word        0          ;Weight of items carried.
  81. CurScore    word        15          ;Player's current score.
  82. TotalCounter    word        9          ;Items left to place.
  83. Noun        word        0          ;Current noun value.
  84. Verb        word        0          ;Current verb value.
  85. NounPtr        word        0          ;Ptr to current noun item.
  86.  
  87.  
  88. ; Input buffer for commands
  89.  
  90. InputLine    byte    128 dup (?)
  91.  
  92.  
  93.  
  94. ; The following macros generate a pattern which will match a single word
  95. ; which appears anywhere on a line.  In particular, they match a word
  96. ; at the beginning of a line, somewhere in the middle of the line, or
  97. ; at the end of a line.  This program defines a word as any sequence
  98. ; of character surrounded by spaces or the beginning or end of a line.
  99. ;
  100. ; MatchNoun/Verb matches lines defined by the regular expression:
  101. ;
  102. ;    (ARB* ' ' | <empty string>) string (' ' | EOS)
  103.  
  104. MatchNoun    macro        Name, next, WordString, ItemVal, ItemPtr
  105.         local        WS1, WS2, WS3, WS4
  106.         local        WS5, WS6, WordStr
  107.  
  108. Name        Pattern        {sl_match2, WS1, next}
  109. WS1        Pattern        {MatchStr, WordStr, WS2, WS5}
  110. WS2        Pattern        {arb,0,0,WS3}
  111. WS3        Pattern        {Matchchar, ' ',0, WS4}
  112. WS4        Pattern        {MatchStr, WordStr, 0, WS5}
  113. WS5        Pattern        {SetNoun,ItemVal,0,WS6}
  114. WS6        Pattern        {SetPtr, ItemPtr,0,MatchEOS}
  115. WordStr        byte        WordString
  116.         byte        0
  117.         endm
  118.  
  119.  
  120. MatchVerb    macro        Name, next, WordString, ItemVal
  121.         local        WS1, WS2, WS3, WS4
  122.         local        WS5, WordStr
  123.  
  124. Name        Pattern        {sl_match2, WS1, next}
  125. WS1        Pattern        {MatchStr, WordStr, WS2, WS5}
  126. WS2        Pattern        {arb,0,0,WS3}
  127. WS3        Pattern        {Matchchar, ' ',0, WS4}
  128. WS4        Pattern        {MatchStr, WordStr, 0, WS5}
  129. WS5        Pattern        {SetVerb,ItemVal,0,MatchEOS}
  130. WordStr        byte        WordString
  131.         byte        0
  132.         endm
  133.  
  134.  
  135.  
  136.  
  137. ; Generic patterns which most of the patterns use:
  138.  
  139. MatchEOS    Pattern        {EOS,0,MatchSpc}
  140. MatchSpc    Pattern        {MatchChar,' '}
  141.  
  142.  
  143. ; Here are the list of nouns allowed in this program.
  144.  
  145. NounPat        pattern        {sl_match2, MatchNorth}
  146.  
  147.         MatchNoun    MatchNorth, MatchSouth, "NORTH", 1, 0
  148.         MatchNoun    MatchSouth, MatchEast, "SOUTH", 2, 0
  149.         MatchNoun    MatchEast, MatchWest, "EAST", 3, 0
  150.         MatchNoun    MatchWest, MatchLime, "WEST", 4, 0
  151.         MatchNoun    MatchLime, MatchBeer, "LIME", 5, Item3
  152.         MatchNoun    MatchBeer, MatchCard, "BEER", 6, Item9
  153.         MatchNoun    MatchCard, MatchSign, "CARD", 7, Item2
  154.         MatchNoun    MatchSign, MatchPgm, "SIGN", 8, Item1
  155.         MatchNoun    MatchPgm,  MatchHW, "PROGRAM", 9, Item7
  156.         MatchNoun    MatchHW,   MatchMoney, "HOMEWORK", 10, Item4
  157.         MatchNoun    MatchMoney, MatchForm, "MONEY", 11, Item5
  158.         MatchNoun    MatchForm,  MatchCoupon, "FORM", 12, Item6
  159.         MatchNoun    MatchCoupon, 0, "COUPON", 13, Item8
  160.  
  161.  
  162. ; Here is the list of allowable verbs.
  163.  
  164. VerbPat        pattern        {sl_match2, MatchGo}
  165.  
  166.         MatchVerb    MatchGO, MatchGet, "GO", 1
  167.         MatchVerb    MatchGet, MatchDrop, "GET", 2
  168.         MatchVerb    MatchDrop, MatchInv, "DROP", 3
  169.         MatchVerb    MatchInv,  MatchQuit, "INVENTORY", 4
  170.         MatchVerb    MatchQuit, MatchHelp, "QUIT", 5
  171.         MatchVerb    MatchHelp, 0, "HELP", 6
  172.  
  173.  
  174. ; Data structures for the "maze".
  175.  
  176. Room1        room        {Room1, Room5, Room4, Room2,
  177.                  {Item1,0,0,0},
  178.                  Room1Desc}
  179.  
  180. Room1Desc    byte        "at the Commons",0
  181.  
  182. Item1        item        {10,2,Room3,GS1,GS2,GS3}
  183. GS1        byte        "a big sign",0
  184. GS2        byte        "a big sign made of styrofoam with funny "
  185.         byte        "letters on it.",0
  186. GS3        byte        "The ETA PI Fraternity thanks you for return"
  187.         byte        "ing their sign, they",cr,lf
  188.         byte        "make you an honorary life member, as long as "
  189.         byte        "you continue to pay",cr,lf
  190.         byte        "your $30 monthly dues, that is.",0
  191.  
  192.  
  193.  
  194.  
  195. Room2        room        {NULL, Room5, Room1, Room3,
  196.                  {Item2,0,0,0},
  197.                  Room2Desc}
  198.  
  199. Room2Desc    byte        'at the "C" on the hill above campus',0
  200.  
  201. Item2        item        {10,1,Room1,LC1,LC2,LC3}
  202. LC1        byte        "a lunch card",0
  203. LC2        byte        "a lunch card which someone must have "
  204.         byte        "accidentally dropped here.", 0
  205. LC3        byte        "You get a big meal at the Commons cafeteria"
  206.         byte        cr,lf
  207.         byte        "It would be a good idea to go visit the "
  208.         byte        "student health center",cr,lf
  209.         byte        "at this time.",0
  210.  
  211.  
  212.  
  213.  
  214. Room3        room        {NULL, Room6, Room2, Room2,
  215.                  {Item3,0,0,0},
  216.                  Room3Desc}
  217.  
  218. Room3Desc    byte        "at ETA PI Frat House",0
  219.  
  220. Item3        item        {10,2,Room2,BL1,BL2,BL3}
  221. BL1        byte        "a bag of lime",0
  222. BL2        byte        "a bag of baseball field lime which someone "
  223.         byte        "is obviously saving for",cr,lf
  224.         byte        "a special occasion.",0
  225. BL3        byte        "You spread the lime out forming a big '++' "
  226.         byte        "after the 'C'",cr,lf
  227.         byte        "Your friends in Computer Science hold you "
  228.         byte        "in total awe.",0
  229.  
  230.  
  231.  
  232.  
  233. Room4        room        {Room1, Room7, Room7, Room5,
  234.                  {Item4,0,0,0},
  235.                  Room4Desc}
  236.  
  237. Room4Desc    byte        "in Dr. John Smith's Office",0
  238.  
  239. Item4        item        {10,1,Room7,HW1,HW2,HW3}
  240. HW1        byte        "a homework assignment",0
  241. HW2        byte        "a homework assignment which appears to "
  242.         byte        "to contain assembly language",0
  243. HW3        byte        "The grader notes that your homework "
  244.         byte        "assignment looks quite",cr,lf
  245.         byte        "similar to someone else's assignment "
  246.         byte        "in the class and reports you",cr,lf
  247.         byte        "to the instructor.",0
  248.  
  249.  
  250.  
  251.  
  252. Room5        room        {Room1, Room9, Room7, Room2,
  253.                  {Item5,0,0,0},
  254.                  Room5Desc}
  255.  
  256. Room5Desc    byte         "in the computer lab",0
  257.  
  258. Item5        item        {10,1,Room9,M1,M2,M3}
  259. M1        byte        "some money",0
  260. M2        byte        "several dollars in an envelope in the "
  261.         byte        "trashcan",0
  262. M3        byte        "The waitress thanks you for your "
  263.         byte        "generous tip and gets you",cr,lf
  264.         byte        "another pitcher of beer.  "
  265.         byte        "Then she asks for your ID.",cr,lf
  266.         byte        "You are at least 21 aren't you?",0
  267.  
  268.  
  269.  
  270.  
  271.  
  272. Room6        room        {Room3, Room9, Room5, NULL,
  273.                  {Item6,0,0,0},
  274.                  Room6Desc}
  275.  
  276. Room6Desc    byte        "at the campus book store",0
  277.  
  278. Item6        item        {10,1,Room8,AD1,AD2,AD3}
  279. AD1        byte        "an add/drop/change form",0
  280. AD2        byte        "an add/drop/change form filled out for "
  281.         byte        "assembly to get a letter grade",0
  282. AD3        byte        "You got the form in just in time.  "
  283.         byte        "It would have been a shame to",cr,lf
  284.         byte        "have had to retake assembly because "
  285.         byte        "you didn't realize you needed to ",cr,lf
  286.         byte        "get a letter grade in the course.",0
  287.  
  288.  
  289.  
  290. Room7        room        {Room1, Room7, Room4, Room8,
  291.                  {Item7,0,0,0},
  292.                  Room7Desc}
  293.  
  294. Room7Desc    byte         "in the assembly lecture",0
  295.  
  296. Item7        item        {10,1,Room5,AP1,AP2,AP3}
  297. AP1        byte        "an assembly language program",0
  298. AP2        byte        "an assembly language program due in "
  299.         byte        "the assemblylanguage class.",0
  300. AP3        byte        "The sample program the instructor gave "
  301.         byte        "you provided all the information",cr,lf
  302.         byte        "you needed to complete your assignment.  "
  303.         byte        "You finish your work and",cr,lf
  304.         byte        "head to the local pub to celebrate."
  305.         byte        cr,lf,0
  306.  
  307.  
  308.  
  309.  
  310. Room8        room        {Room5, Room6, Room7, Room9,
  311.                  {Item8,0,0,0},
  312.                  Room8Desc}
  313.  
  314. Room8Desc    byte         "at the Registrar's office",0
  315.  
  316. Item8        item        {10,1,Room6,C1,C2,C3}
  317. C1        byte        "a coupon",0
  318. C2        byte        "a coupon good for a free text book",0
  319. C3        byte        'You get a free copy of "Cliff Notes for '
  320.         byte        'The Art of Assembly',cr,lf
  321.         byte        'Language Programming"  Alas, it does not '
  322.         byte        "provide all the",cr,lf
  323.         byte        "information you need for the class, so you "
  324.         byte        "sell it back during",cr,lf
  325.         byte        "the book buy-back period.",0
  326.  
  327.  
  328.  
  329. Room9        room        {Room6, Room9, Room8, Room3,
  330.                  {Item9,0,0,0},
  331.                  Room9Desc}
  332.  
  333. Room9Desc    byte        "at The Pub",0
  334. Item9        item        {10,2,Room4,B1,B2,B3}
  335. B1        byte        "a pitcher of beer",0
  336. B2        byte        "an ice cold pitcher of imported beer",0
  337. B3        byte        "Dr. Smith thanks you profusely for your "
  338.         byte        "good taste in brews.",cr,lf
  339.         byte        "He then invites you to the pub for a "
  340.         byte        "round of pool and",cr,lf
  341.         byte        "some heavy duty hob-nobbing, "
  342.         byte        "CS Department style.",0
  343.  
  344.  
  345. dseg        ends
  346.  
  347.  
  348.  
  349.  
  350.  
  351. cseg        segment        para public 'code'
  352.         assume        ds:dseg
  353.  
  354.  
  355. ; SetNoun-    Copies the value in SI (the matchparm parameter) to the
  356. ;        NOUN variable.
  357.  
  358. SetNoun        proc    far
  359.         push    ds
  360.         mov    ax, dseg
  361.         mov    ds, ax
  362.         mov    Noun, si
  363.         mov    ax, di
  364.         stc
  365.         pop    ds
  366.         ret
  367. SetNoun        endp
  368.  
  369.  
  370. ; SetVerb-    Copies the value in SI (the matchparm parameter) to the
  371. ;        VERB variable.
  372.  
  373. SetVerb        proc    far
  374.         push    ds
  375.         mov    ax, dseg
  376.         mov    ds, ax
  377.         mov    Verb, si
  378.         mov    ax, di
  379.         stc
  380.         pop    ds
  381.         ret
  382. SetVerb        endp
  383.  
  384. ; SetPtr-    Copies the value in SI (the matchparm parameter) to the
  385. ;        NOUNPTR variable.
  386.  
  387. SetPtr        proc    far
  388.         push    ds
  389.         mov    ax, dseg
  390.         mov    ds, ax
  391.         mov    NounPtr, si
  392.         mov    ax, di
  393.         stc
  394.         pop    ds
  395.         ret
  396. SetPtr        endp
  397.  
  398.  
  399.  
  400. ; CheckPresence-
  401. ;        BX points at an item.  DI points at an item list.  This
  402. ;        routine checks to see if that item is present in the
  403. ;        item list.  Returns Carry set if item was found,
  404. ;        clear if not found.
  405.  
  406. CheckPresence    proc
  407.  
  408. ; MaxWeight is an assembly-time adjustable constant that determines
  409. ; how many objects the user can carry, or can be in a room, at one
  410. ; time.  The following repeat macro emits "MaxWeight" compare and
  411. ; branch sequences to test each item pointed at by DS:DI.
  412.  
  413. ItemCnt        =    0
  414.         repeat    MaxWeight
  415.         cmp    bx, [di+ItemCnt]
  416.         je    GotIt
  417.  
  418. ItemCnt        =    ItemCnt+2
  419.         endm
  420.  
  421.         clc
  422.         ret
  423.  
  424. GotIt:        stc
  425.         ret
  426. CheckPresence    endp
  427.  
  428.  
  429.  
  430. ; RemoveItem-    BX contains a pointer to an item.  DI contains a pointer
  431. ;        to an item list which contains that item.  This routine
  432. ;        searches the item list and removes that item from the
  433. ;        list.  To remove an item from the list, we need only
  434. ;         store a zero (NULL) over the top of its pointer entry
  435. ;        in the list.
  436.  
  437. RemoveItem    proc
  438.  
  439. ; Once again, we use the repeat macro to automatically generate a chain
  440. ; of compare, branch, and remove code sequences for each possible item
  441. ; in the list.
  442.  
  443. ItemCnt        =    0
  444.         repeat    MaxWeight
  445.         local    NotThisOne
  446.         cmp    bx, [di+ItemCnt]
  447.         jne    NotThisOne
  448.         mov    word ptr [di+ItemCnt], NULL
  449.         ret
  450. NotThisOne:
  451. ItemCnt        =    ItemCnt+2
  452.         endm
  453.  
  454.         ret
  455. RemoveItem    endp
  456.  
  457.  
  458. ; InsertItem-    BX contains a pointer to an item, DI contains a pointer to
  459. ;        and item list.  This routine searches through the list for
  460. ;        the first empty spot and copies the value in BX to that point.
  461. ;        It returns the carry set if it succeeds.  It returns the
  462. ;        carry clear if there are no empty spots available.
  463.  
  464. InsertItem    proc
  465.  
  466. ItemCnt        =    0
  467.         repeat    MaxWeight
  468.         local    NotThisOne
  469.         cmp    word ptr [di+ItemCnt], 0
  470.         jne    NotThisOne
  471.         mov    [di+ItemCnt], bx
  472.         stc
  473.         ret
  474. NotThisOne:
  475. ItemCnt        =    ItemCnt+2
  476.         endm
  477.  
  478.         clc
  479.         ret
  480. InsertItem    endp
  481.  
  482.  
  483.  
  484.  
  485.  
  486. ; LongDesc- Long description of an item.
  487. ; DI points at an item - print the long description of it.
  488.  
  489. LongDesc    proc
  490.         push    di
  491.         test    di, di
  492.         jz    NoDescription
  493.         mov    di, [di].item.LongDesc
  494.         puts
  495.         putcr
  496. NoDescription:    pop    di
  497.         ret
  498. LongDesc    endp
  499.  
  500.  
  501. ; ShortDesc- Print the short description of an object.
  502. ; DI points at an item (possibly NULL).  Print the short description for it.
  503.  
  504. ShortDesc    proc
  505.         push    di
  506.         test    di, di
  507.         jz    NoDescription
  508.         mov    di, [di].item.ShortDesc
  509.         puts
  510.         putcr
  511. NoDescription:    pop    di
  512.         ret
  513. ShortDesc    endp
  514.  
  515.  
  516.  
  517.  
  518. ; Describe:     "CurRoom" points at the current room.  Describe it and its
  519. ;        contents.
  520.  
  521. Describe    proc
  522.         push    es
  523.         push    bx
  524.         push    di
  525.         mov    di, ds
  526.         mov    es, di
  527.  
  528.         mov    bx, CurRoom
  529.         mov    di, [bx].room.Description
  530.         print
  531.         byte    "You are currently ",0
  532.         puts
  533.         putcr
  534.         print
  535.         byte    "Here you find the following:",cr,lf,0
  536.  
  537. ; For each possible item in the room, print out the long description
  538. ; of that item.  The repeat macro generates a code sequence for each
  539. ; possible item that could be in this room.
  540.  
  541. ItemCnt        =    0
  542.         repeat    MaxWeight
  543.         mov    di, [bx].room.ItemList[ItemCnt]
  544.         call    LongDesc
  545.  
  546. ItemCnt        =    ItemCnt+2
  547.         endm
  548.  
  549.  
  550.         pop    di
  551.         pop    bx
  552.         pop    es
  553.         ret
  554. Describe    endp
  555.  
  556.  
  557.  
  558.  
  559.  
  560.  
  561. ; Here is the main program, which actually plays the game.
  562.  
  563. Main        proc
  564.         mov    ax, dseg
  565.         mov    ds, ax
  566.         mov    es, ax
  567.         meminit
  568.  
  569.         print
  570.         byte    cr,lf,lf,lf,lf,lf
  571.         byte    "Welcome to ",'"MADVENTURE"',cr,lf
  572.         byte    'If you need help, type the command "HELP"'
  573.         byte    cr,lf,0
  574.  
  575. RoomLoop:    dec    CurScore        ;One point for each move.
  576.         jnz    NotOverYet
  577.  
  578. ; If they made too many moves without dropping anything properly, boot them
  579. ; out of the game.
  580.  
  581.         print
  582.         byte    "WHOA!  You lost!  You get to join the legions of "
  583.         byte    "the totally lame",cr,lf
  584.         byte    'who have failed at "MADVENTURE"',cr,lf,0
  585.         jmp    Quit
  586.  
  587. ; Okay, tell 'em where they are and get a new command from them.
  588.  
  589. NotOverYet:    putcr
  590.         call    Describe
  591.         print
  592.         byte    cr,lf
  593.         byte    "Command: ",0
  594.         lesi    InputLine
  595.         gets
  596.         strupr            ;Ignore case by converting to U.C.
  597.  
  598. ; Okay, process the command.  Note that we don't actually check to see
  599. ; if there is a properly formed sentence.  Instead, we just look to see
  600. ; if any important keywords are on the line.  If they are, the pattern
  601. ; matching routines load the appropriate values into the noun and verb
  602. ; variables (nouns: north=1, south=2, east=3, west=4, lime=5, beer=6,
  603. ; card=7, sign=8, program=9, homework=10, money=11, form=12, coupon=13;
  604. ; verbs: go=1, get=2, drop=3, inventory=4, quit=5, help=6).
  605. ;
  606. ; This code uses the noun and verb variables as indexes into a two
  607. ; dimensional array whose elements contain the address of the code
  608. ; to process the given command.  If a given command does not make
  609. ; any sense (e.g., "go coupon") the entry in the table points at the
  610. ; bad command code.
  611.  
  612.         mov    Noun, 0
  613.         mov    Verb, 0
  614.         mov    NounPtr, 0
  615.  
  616.         ldxi    VerbPat
  617.         xor    cx, cx
  618.         match
  619.  
  620.         lesi    InputLine
  621.         ldxi    NounPat
  622.         xor    cx, cx
  623.         match
  624.  
  625. ; Okay, index into the command table and jump to the appropriate
  626. ; handler.  Note that we will cheat and use a 14x8 array.  There
  627. ; are really only seven verbs, not eight.  But using eight makes
  628. ; things easier since it is easier to multiply by eight than seven.
  629.  
  630.         mov    si, CurRoom    ;The commands expect this here.
  631.  
  632.         mov    bx, Noun
  633.         shl    bx, 3        ;Multiply by eight.
  634.         add    bx, Verb
  635.         shl    bx, 1        ;Multiply by two - word table.
  636.         jmp    cseg:jmptbl[bx]
  637.  
  638. ; The following table contains the noun x verb cross product.
  639. ; The verb values (in each row) are the following:
  640. ;
  641. ;    NONE    GO    GET    DROP    INVNTRY    QUIT    HELP    unused
  642. ;     0     1     2     3      4     5     6      7
  643. ;
  644. ; There is one row for each noun (plus row zero, corresponding to no
  645. ; noun found on line).
  646.  
  647. jmptbl        word    Bad        ;No noun, no verb
  648.         word    Bad        ;No noun, GO
  649.         word    Bad        ;No noun, GET
  650.         word    Bad        ;No noun, DROP
  651.         word    DoInventory    ;No noun, INVENTORY
  652.         word    QuitGame    ;No noun, QUIT
  653.         word    DoHelp        ;No noun, HELP
  654.         word    Bad        ;N/A
  655.  
  656. NorthCmds    word    Bad, GoNorth, Bad, Bad, Bad, Bad, Bad, Bad
  657. SouthCmds    word    Bad, GoSouth, Bad, Bad, Bad, Bad, Bad, Bad
  658. EastCmds    word    Bad, GoEast, Bad, Bad, Bad, Bad, Bad, Bad
  659. WestCmds    word    Bad, GoWest, Bad, Bad, Bad, Bad, Bad, Bad
  660. LimeCmds    word    Bad, Bad, GetItem, DropItem, Bad, Bad, Bad, Bad
  661. BeerCmds    word    Bad, Bad, GetItem, DropItem, Bad, Bad, Bad, Bad
  662. CardCmds    word    Bad, Bad, GetItem, DropItem, Bad, Bad, Bad, Bad
  663. SignCmds    word    Bad, Bad, GetItem, DropItem, Bad, Bad, Bad, Bad
  664. ProgramCmds    word    Bad, Bad, GetItem, DropItem, Bad, Bad, Bad, Bad
  665. HomeworkCmds    word    Bad, Bad, GetItem, DropItem, Bad, Bad, Bad, Bad
  666. MoneyCmds    word    Bad, Bad, GetItem, DropItem, Bad, Bad, Bad, Bad
  667. FormCmds    word    Bad, Bad, GetItem, DropItem, Bad, Bad, Bad, Bad
  668. CouponCmds    word    Bad, Bad, GetItem, DropItem, Bad, Bad, Bad, Bad
  669.  
  670. ; If the user enters a command we don't know how to process, print an
  671. ; appropriate error message down here.
  672.  
  673. Bad:        printf
  674.         byte    "I'm sorry, I don't understand how to '%s'\n",0
  675.         dword    InputLine
  676.         jmp    NotOverYet
  677.  
  678.  
  679. ; Handle the movement commands here.
  680. ; Movements are easy, all we've got to do is fetch the NORTH, SOUTH,
  681. ; EAST, or WEST pointer from the current room's data structure and
  682. ; set the current room to that address.  The only catch is that some
  683. ; moves are not legal.  Such moves have a NULL (zero) in the direction
  684. ; field.  A quick check for this case handles illegal moves.
  685.  
  686. GoNorth:    mov    si, [si].room.North
  687.         jmp    MoveMe
  688.  
  689. GoSouth:    mov    si, [si].room.South
  690.         jmp    MoveMe
  691.  
  692. GoEast:        mov    si, [si].room.East
  693.         jmp    MoveMe
  694.  
  695. GoWest:        mov    si, [si].room.West
  696. MoveMe:        test    si, si            ;See if move allowed.
  697.         jnz    SetCurRoom
  698.         printf
  699.         byte    "Sorry, you cannot go in this direction."
  700.         byte    cr, lf, 0
  701.         jmp    RoomLoop
  702.  
  703. SetCurRoom:    mov    CurRoom, si        ;Move to new room.
  704.         jmp    RoomLoop
  705.  
  706.  
  707. ; Handle the GetItem command down here.  At this time the user
  708. ; has entered GET and some noun that the player can pick up.
  709. ; First, we will make sure that item is in this room.
  710. ; Then we will check to make sure that picking up this object
  711. ; won't overload the player.  If these two conditions are met,
  712. ; we'll transfer the object from the room to the player.
  713.  
  714. GetItem:    mov    bx, NounPtr        ;Ptr to item user wants.
  715.         mov    si, CurRoom
  716.         lea    di, [si].room.ItemList    ;Ptr to item list in di.
  717.         call    CheckPresence        ;See if in room.
  718.         jc    GotTheItem
  719.         printf
  720.         byte    "Sorry, that item is not available here."
  721.         byte    cr, lf, 0
  722.         jmp    RoomLoop
  723.  
  724. ; Okay, see if picking up this object will overload the player.
  725.  
  726. GotTheItem:    mov    ax, [bx].Item.Weight
  727.         add    ax, CurWeight
  728.         cmp    ax, MaxWeight
  729.         jbe    WeightOkay
  730.         printf
  731.         byte    "Sorry, you are already carrying too many items "
  732.         byte    "to safely carry\nthat object\n",0
  733.         jmp    RoomLoop
  734.  
  735. ; Okay, everything's cool, transfer the object from the room to the user.
  736.  
  737. WeightOkay:    mov    CurWeight, ax        ;Save new weight.
  738.         call    RemoveItem        ;Remove item from room.
  739.         lea    di, ItemsOnHand        ;Ptr to player's list.
  740.         call    InsertItem
  741.         jmp    RoomLoop
  742.  
  743.  
  744. ; Handle dropped objects down here.
  745.  
  746. DropItem:    lea    di, ItemsOnHand        ;See if the user has
  747.         mov    bx, NounPtr        ; this item on hand.
  748.         call    CheckPresence
  749.         jc    CanDropIt1
  750.         printf
  751.         byte    "You are not currently holding that item\n",0
  752.         jmp    RoomLoop
  753.  
  754. ; Okay, let's see if this is the magic room where this item is
  755. ; supposed to be dropped.  If so, award the user some points for
  756. ; properly figuring this out.
  757.  
  758. CanDropIt1:    mov    ax, [bx].item.key
  759.         cmp    ax, CurRoom
  760.         jne    JustDropIt
  761.  
  762. ; Okay, success!  Print the winning message for this object.
  763.  
  764.         mov    di, [bx].item.WinDesc
  765.         puts
  766.         putcr
  767.  
  768. ; Award the user some points.
  769.  
  770.         mov    ax, [bx].item.value
  771.         add    CurScore, ax
  772.  
  773. ; Since the user dropped it, they can carry more things now.
  774.  
  775.         mov    ax, [bx].item.Weight
  776.         sub    CurWeight, ax
  777.  
  778. ; Okay, take this from the user's list.
  779.  
  780.         lea    di, ItemsOnHand
  781.         call    RemoveItem
  782.  
  783. ; Keep track of how may objects the user has successfully dropped.
  784. ; When this counter hits zero, the game is over.
  785.  
  786.         dec    TotalCounter
  787.         jnz    RoomLoop
  788.  
  789.         printf
  790.         byte    "Well, you've found where everything goes "
  791.         byte    "and your score is %d.\n"
  792.         byte    "You might want to play again and see if "
  793.         byte    "you can get a better score.\n",0
  794.         dword    CurScore
  795.         jmp    Quit
  796.  
  797.  
  798. ; If this isn't the room where this object belongs, just drop the thing
  799. ; off.  If this object won't fit in this room, ignore the drop command.
  800.  
  801. JustDropIt:    mov    di, CurRoom
  802.         lea    di, [di].room.ItemList
  803.         call    InsertItem
  804.         jc    DroppedItem
  805.         printf
  806.         byte    "There is insufficient room to leave "
  807.         byte    "that item here.\n",0
  808.         jmp    RoomLoop
  809.  
  810. ; If they can drop it, do so.  Don't forget we've just unburdened the
  811. ; user so we need to deduct the weight of this object from what the
  812. ; user is currently carrying.
  813.  
  814. DroppedItem:    lea    di, ItemsOnHand
  815.         call    RemoveItem
  816.         mov    ax, [bx].item.Weight
  817.         sub    CurWeight, ax
  818.         jmp    RoomLoop
  819.  
  820.  
  821. ; If the user enters the INVENTORY command, print out the objects on hand
  822.  
  823. DoInventory:    printf
  824.         byte    "You currently have the following items in your "
  825.         byte    "possession:",cr,lf,0
  826.         mov    di, ItemsOnHand[0]
  827.         call    ShortDesc
  828.         mov    di, ItemsOnHand[2]
  829.         call    ShortDesc
  830.         mov    di, ItemsOnHand[4]
  831.         call    ShortDesc
  832.         mov    di, ItemsOnHand[6]
  833.         call    ShortDesc
  834.         printf
  835.         byte    "\nCurrent score: %d\n"
  836.         byte    "Carrying ability: %d/4\n\n",0
  837.         dword    CurScore,CurWeight
  838.         inc    CurScore        ;This command is free.
  839.         jmp    RoomLoop
  840.  
  841.  
  842. ; If the user requests help, provide it here.
  843.  
  844. DoHelp:        printf
  845.         byte    "List of commands:",cr,lf,lf
  846.         byte    "GO {NORTH, EAST, WEST, SOUTH}",cr,lf
  847.         byte    "{GET, DROP} {LIME, BEER, CARD, SIGN, PROGRAM, "
  848.         byte    "HOMEWORK, MONEY, FORM, COUPON}",cr,lf
  849.         byte    "SHOW INVENTORY",cr,lf
  850.         byte    "QUIT GAME",cr,lf
  851.         byte    "HELP ME",cr,lf,lf
  852.         byte    "Each command costs you one point.",cr,lf
  853.         byte    "You accumulate points by picking up objects and "
  854.         byte    "dropping them in their",cr,lf
  855.         byte    "  appropriate locations.",cr,lf
  856.         byte    "If you drop an item in its proper location, it "
  857.         byte    "disappears from the game.",cr,lf
  858.         byte    "The game is over if your score drops to zero or "
  859.         byte    "you properly place",cr,lf
  860.         byte    "  all items.",cr,lf
  861.         byte    0
  862.         jmp    RoomLoop
  863.  
  864.  
  865. ; If they quit prematurely, let 'em know what a wimp they are!
  866.  
  867. QuitGame:    printf
  868.         byte    "So long, your score is %d and there are "
  869.         byte    "still %d objects unplaced\n",0
  870.         dword    CurScore, TotalCounter
  871.  
  872.  
  873. Quit:        ExitPgm            ;DOS macro to quit program.
  874. Main        endp
  875. cseg        ends
  876.  
  877. sseg        segment    para stack 'stack'
  878. stk        db    1024 dup ("stack   ")
  879. sseg        ends
  880.  
  881. zzzzzzseg    segment    para public 'zzzzzz'
  882. LastBytes    db    16 dup (?)
  883. zzzzzzseg    ends
  884.         end    Main
  885.